package org.devocean.groupbuying.web.backend;

import java.security.Principal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.devocean.groupbuying.domain.Article;
import org.devocean.groupbuying.domain.Compatibility;
import org.devocean.groupbuying.domain.Formula;
import org.devocean.groupbuying.domain.Plan;
import org.devocean.groupbuying.domain.Promotion;
import org.devocean.groupbuying.service.FormulaService;
import org.devocean.groupbuying.service.PlanService;
import org.devocean.groupbuying.service.PromotionService;
import org.devocean.groupbuying.service.UserService;
import org.devocean.groupbuying.utils.RenderMapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping(value = "/gb-cpanel/plans")
public class PlansController {
	
	@Autowired
	private PlanService planService;

	
	@Autowired
	private UserService userService;
	
	@Autowired
	private FormulaService formulaService;
	
	@Autowired
	private PromotionService promotionService;

	@RequestMapping(value = "/", method = RequestMethod.POST)
	public @ResponseBody
	Map<String, ? extends Object> addOrUpdate(@RequestBody Plan plan,Principal principal) {
	
		try {
			plan.getArticlesLocalization()
					.getArticles()
					.iterator().next()
					.setOwner(
							userService.getUserById(Integer.valueOf(principal
									.getName())));
			
			Plan newPlan = planService.addOrUpdatePlan(plan);
			return RenderMapUtils.getMap(this.renderPlan(newPlan));
		} catch (Exception e) {
			e.printStackTrace();
			return RenderMapUtils
					.getModelMapError("Error saving Plans into database.");
		}

	}
	@RequestMapping(value = "/promotion", method = RequestMethod.POST)
	public @ResponseBody Map<String, ? extends Object> addOrUpdatePromotion(@RequestBody Promotion promotion) {
		try {
			promotion = promotionService.addOrUpdatePromotion(promotion);
			Map<String, Object> data = new ConcurrentHashMap<String, Object>();
			data.put("promotionID", promotion.getPromotionID());
			return RenderMapUtils.getMap(data);
		} catch (Exception e) {
			e.printStackTrace();
			return RenderMapUtils
					.getModelMapError("Error saving Promotion into database.");
		}
		
	}
	@RequestMapping(value="/promotions/plan/{planID}",method=RequestMethod.GET)
	public Map<String, ? extends Object> getPromotions(@PathVariable("planID") Integer planID){
				
		try{
			List<Promotion> promotions = promotionService.getPromotionsByPlan(planID);
			SimpleDateFormat simpleFormat = new SimpleDateFormat("MM/dd/yyyy");
			List<Map<String, Object>> promotionsList = new ArrayList<Map<String, Object>>();
			for(Promotion promotion : promotions){
				Map<String, Object> promotionsmap = new  ConcurrentHashMap<String, Object>();
				promotionsmap.put("promotionID", promotion.getPromotionID());
				promotionsmap.put("title", promotion.getTitle());
				Date expireDate = promotion.getExpireDate();
				Date today = Calendar.getInstance().getTime();
				promotionsmap.put("expireDate",expireDate.before(today)?"Expired Promotion": simpleFormat.format(promotion.getExpireDate()));
				promotionsmap.put("planID", promotion.getPlan().getPlanID());
				promotionsList.add(promotionsmap);
			}
			return RenderMapUtils.getMap(promotionsList,promotionsList.size()) ;
			
		
		}catch (Exception e) {
			e.printStackTrace();
		return RenderMapUtils
				.getModelMapError("Error retrieving Promotions from database.");
	}
	}
	@RequestMapping(value="/promotion/{promotionID}",method=RequestMethod.GET)
	public Map<String, ? extends Object> getPromotion(@PathVariable("promotionID") Integer promotionID){
				
		try{
			Promotion promotion = promotionService.getPromotionById(promotionID);
			Map<String, Object> data = new ConcurrentHashMap<String, Object>();
			SimpleDateFormat simpleFormat = new SimpleDateFormat("MM/dd/yyyy");
			data.put("promotionID", promotion.getPromotionID());
			data.put("title", promotion.getTitle());
			data.put("commission", promotion.getCommission() ==null?0:promotion.getCommission());
			data.put("link", promotion.getLink());
			data.put("details", promotion.getDetails());
			data.put("discount", promotion.getDiscount());
			data.put("discounted", promotion.getDiscounted() == null ?0:promotion.getDiscounted());			
			data.put("purchaseNumber", promotion.getPurchaseNumber());
			data.put("expireDate", simpleFormat.format(promotion.getExpireDate()));
			data.put("startDate", simpleFormat.format(promotion.getStartDate()));
			data.put("coupon", promotion.getCoupon());
			data.put("planID", promotion.getPlan().getPlanID());
			return RenderMapUtils.getMap(data);
			
		
		}catch (Exception e) {
			e.printStackTrace();
		return RenderMapUtils
				.getModelMapError("Error retrieving Promotion from database.");
	}
	}
	
	@RequestMapping(value = "/promotions/delete", method = RequestMethod.POST)
	public void deletePrmotions(@RequestParam("requestSelectedPromotions") Integer[] requestSelectedPromotions) {
		
		for (int i = 0; i < requestSelectedPromotions.length; i++) {
			promotionService.removePromotion(requestSelectedPromotions[i]);
		}
		
	}

	@RequestMapping(value = "/formulas/delete", method = RequestMethod.POST)
	public void deleteFormulas(@RequestParam("requestSelectedFormulas") Integer[] requestSelectedFormulas) {
		
		for (int i = 0; i < requestSelectedFormulas.length; i++) {
			formulaService.removeFormula(requestSelectedFormulas[i]);
		}
		
	}

	@RequestMapping(value = "/delete", method = RequestMethod.POST)
	public void deletePlans(@RequestParam("requestSelectedPlans") Integer[] requestSelectedPlans) {
		
		for (int i = 0; i < requestSelectedPlans.length; i++) {
			System.out.println(requestSelectedPlans[i]);
			planService.deletePlan(requestSelectedPlans[i]);
		}
		
	}

	@RequestMapping(value="/product/{productID}",method=RequestMethod.GET)
	public Map<String, ? extends Object> getPlans(
			@PathVariable("productID") Integer productID,
			@RequestParam("lang") String lang
				){
		
		
		try{
			List<Plan> plans = planService.getPlansbyProduct(productID,lang);
			List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		
			for (Plan plan : plans) {
				
					result.add(this.renderPlan(plan));
				}
			
			return RenderMapUtils.getMap(result,result.size()) ;
		
		}catch (Exception e) {
		return RenderMapUtils
				.getModelMapError("Error retrieving Articles from database.");
	}
	}
	@RequestMapping(value="/{articleID}",method=RequestMethod.GET)
	public Map<String, ? extends Object> getPlan(@PathVariable("articleID") Integer articleID){
		
		
		try{
			Plan plan = planService.getPlanByArticle(articleID);
			return RenderMapUtils.getMap(this.renderPlan(plan)) ;
			
		
		}catch (Exception e) {
		return RenderMapUtils
				.getModelMapError("Error retrieving Articles from database.");
	}
	}
	
	@RequestMapping(value = "/localize", method = RequestMethod.GET)
	public Map<String, ? extends Object> localize(Integer LocalizationKey,
			String LocalizationRequest) {
		Plan plan = planService.getPlanByLang(LocalizationKey,LocalizationRequest);
		return RenderMapUtils.getMap(this.renderPlan(plan));
	}
	
	public Map<String, Object> renderPlan(Plan plan){
		
		Map<String, Object> data = new ConcurrentHashMap<String, Object>();
		Integer[] comp_ids = new Integer[plan.getCompatibilities().size()];
		data.put("url", plan.getUrl());
		data.put("trial", plan.getTrial());
		if(plan.getArticlesLocalization().getArticles()!=null){
			Article article = plan.getArticlesLocalization().getArticles().iterator().next();
			data.put("title", article.getTitle());
			data.put("shorte", article.getShorte());
			data.put("body",  article.getBody());
			data.put("articleID", article.getArticleID());
			data.put("al_id", plan.getArticlesLocalization().getArticlesLocalizationID());
			data.put("lang", article.getLang());
			
		}
		List<Formula> formulas = new ArrayList<Formula>(plan.getFormulas());
		List<Map<String, Object>> formulasList = new ArrayList<Map<String, Object>>();
		for (Formula formula : formulas) {
			Map<String, Object> formulasmap = new  ConcurrentHashMap<String, Object>();
			formulasmap.put("formulaID", formula.getFormulaID());
			formulasmap.put("currency", formula.getCurrency()==null?"":formula.getCurrency());
			formulasmap.put("choice", formula.getChoice()==null?"":formula.getChoice());
			formulasmap.put("factor", formula.getFactor()==null?"":formula.getFactor());
			formulasmap.put("frequency", formula.getFrequency()==null?"":formula.getFrequency());
			formulasmap.put("price", formula.getPrice()==null?"":formula.getPrice());
			formulasList.add(formulasmap);		
		}
		Iterator<Compatibility> it = plan.getCompatibilities().iterator();
		List<Map<String, Object>> compatibilityList = new ArrayList<Map<String, Object>>();
		int i =0;
		while (it.hasNext()) {
			Compatibility comp = it.next();
			comp_ids[i++]=comp.getCompatibilityID();
			
//			Map<String, Object> compabilitysmap = new  ConcurrentHashMap<String, Object>();
//			compabilitysmap.put("compatibilityID", comp.getCompatibilityID());
//			compabilitysmap.put("compatibilitykey", comp.getCompatibilitykey());
//			compabilitysmap.put("value", comp.getValue());
//			compatibilityList.add(compabilitysmap);
		}
		data.put("compatibilitiesDevice", comp_ids);
		data.put("compatibilitiesLang", comp_ids);
		data.put("compatibilitiesType", comp_ids);
		data.put("formulas", formulasList);
		data.put("productID", plan.getProduct().getProductID());
		data.put("planID", plan.getPlanID());
		data.put("articlesLocalizationID", plan.getArticlesLocalization().getArticlesLocalizationID());
		return data;
	}
}
